package com.le.tester.javaThink.fourth.concurrency;

import org.junit.experimental.theories.DataPoint;

import java.util.*;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * createTime：2022/1/14 10:49
 * description：温室控制，将runnable对象设置在将来的某个时刻执行,使用的是延迟执行runnable
 */
public class GreenhouseScheduler {
    //灯
    private volatile boolean light = false;

    //水
    private volatile boolean water = false;

    //调温
    private String thermostat = "Day";

    public synchronized String getThermostat() {
        return thermostat;
    }

    public synchronized void setThermostat(String thermostat) {
        this.thermostat = thermostat;
    }

    //注意jdk中是默认的给设置了一个延时队列new DelayedWorkQueue，keepAliveTime is 0
    ScheduledThreadPoolExecutor scheduled = new ScheduledThreadPoolExecutor(10);

    public void scheduled(Runnable even, long delay) {
        scheduled.schedule(even, delay, TimeUnit.MILLISECONDS);
    }

    /**
     * @param event        exec task
     * @param initialDelay delay time
     * @param period       周期
     */
    public void repeat(Runnable event, long initialDelay, long period) {
        scheduled.scheduleAtFixedRate(event, initialDelay, period, TimeUnit.MILLISECONDS);
    }

    class LightOn implements Runnable {

        @Override
        public void run() {
            System.out.println("Turning on lights");
            light = true;
        }
    }

    class LightOff implements Runnable {

        @Override
        public void run() {
            System.out.println("Turning ");
        }
    }

    class WaterOn implements Runnable {

        @Override
        public void run() {
            System.out.println("Turning greenhouse water on");
            water = true;
        }
    }

    class WaterOff implements Runnable {

        @Override
        public void run() {
            System.out.println("Turning greenhouse water off");
            water = false;
        }
    }

    class ThermostatNight implements Runnable {

        @Override
        public void run() {
            System.out.println("Thermostat to night setting");
            setThermostat("Night");
        }
    }

    class ThermostatDay implements Runnable {

        @Override
        public void run() {
            System.out.println("Thermostat to day setting");
            setThermostat("Day");
        }
    }

    //响铃提示
    class Bell implements Runnable {

        @Override
        public void run() {
            System.out.println("Bing!");
        }
    }

    //中断
    class Terminate implements Runnable {

        @Override
        public void run() {
            System.out.println("Terminating");
            scheduled.shutdownNow();

            //开启一个新的线程来继续工作
            new Thread(() -> {
                for (DataPoint d : data)
                    System.out.println(d);
            }).start();
        }
    }

    //dataPoint collection
    static class DataPoint {
        final Calendar time;
        final float temperature;
        final float humidity;

        public DataPoint(Calendar time, float temperature, float humidity) {
            this.time = time;
            this.temperature = temperature;
            this.humidity = humidity;
        }

        @Override
        public String toString() {
            return "DataPoint{" +
                    "time=" + time +
                    ", temperature=" + temperature +
                    ", humidity=" + humidity +
                    '}';
        }
    }

    //calendar instance
    private Calendar lastTime = Calendar.getInstance();

    {
        lastTime.set(Calendar.MINUTE, 30);
        lastTime.set(Calendar.SECOND, 0);
    }

    private float lastTemp = 65.0f;
    private int tempDirection = +1;
    private float lastHumidity = 50.0f;
    private int humidityDirection = +1;

    private Random random = new Random(47);

    //同步列表，线程安全
    List<DataPoint> data = Collections.synchronizedList(new ArrayList<>());

    class CollectData implements Runnable {

        @Override
        public void run() {
            System.out.println("Collecting data");
            synchronized (GreenhouseScheduler.this) {
                lastTime.set(Calendar.MINUTE, lastTime.get(Calendar.MINUTE) + 30);
                if (random.nextInt(5) == 4) {
                    tempDirection = -tempDirection;
                }
                lastTemp = lastTemp + tempDirection * (1.0f + random.nextFloat());
                if (random.nextInt(5) == 4) {
                    humidityDirection = -humidityDirection;
                }
                lastHumidity = lastHumidity + humidityDirection * random.nextFloat();
                data.add(new DataPoint((Calendar) lastTime.clone(), lastTemp, lastHumidity));
            }
        }
    }

    public static void main(String[] args) {
        GreenhouseScheduler gh = new GreenhouseScheduler();
        //5000 mill后中断
        gh.scheduled(gh.new Terminate(), 5000);
        //per 1000 mill bell
        gh.repeat(gh.new Bell(), 0, 1000);
        //调到晚上的温度
        gh.repeat(gh.new ThermostatNight(), 0, 2000);
        gh.repeat(gh.new LightOn(), 0, 200);
        gh.repeat(gh.new LightOff(), 0, 400);
        gh.repeat(gh.new WaterOn(), 0, 600);
        gh.repeat(gh.new WaterOff(), 0, 800);
        gh.repeat(gh.new ThermostatDay(), 0, 1400);
        gh.repeat(gh.new CollectData(), 500, 500);
    }

}
